﻿using System;
using System.Diagnostics;
using System.Text;
using NLog;
using NLog.Targets;

namespace Game.Utilities.Log
{
    public static class NLogManager
    {
        /// <summary>
        /// 
        /// </summary>
        volatile static Logger _log;

        private static Logger Log
        {
            get
            {
                if (_log == null)
                {
                    try
                    {
                        if (LogManager.Configuration != null && LogManager.Configuration.LoggingRules.Count > 0)
                        {
                            _log = LogManager.GetCurrentClassLogger();

                            return _log;
                        }
                    }
                    catch
                    {
                    }

                    FileTarget target = new FileTarget();
                    target.Layout = "${longdate} ${logger} ${message}";
                    target.FileName = "${basedir}/_LOG/${date:format=yyyyMMdd}_Debug.txt";
                    target.ArchiveFileName = "${basedir}/archives/${date:format=yyyyMMdd}_Debug_log.txt";
                    target.ArchiveAboveSize = 1024 * 1024 * 100; // archive files greater than 10 KB
                    //   target.ArchiveNumbering = FileTarget.ArchiveNumberingMode.Sequence;
                    target.Name = "Debug";
                    // this speeds up things when no other processes are writing to the file
                    target.ConcurrentWrites = true;

                    NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Debug);

                    FileTarget warning = new FileTarget();
                    warning.Layout = "${longdate} ${logger} ${message}";
                    warning.FileName = "${basedir}/_LOG/${date:format=yyyyMMdd}_Portal.txt";
                    warning.ArchiveFileName = "${basedir}/archives/${date:format=yyyyMMdd}_Portal_log.txt";
                    warning.ArchiveAboveSize = 1024 * 1024 * 100; // archive files greater than 10 KB
                    //   warning.ArchiveNumbering = FileTarget.ArchiveNumberingMode.Sequence;
                    warning.Name = "Warning";
                    // this speeds up things when no other processes are writing to the file
                    warning.ConcurrentWrites = true;
                    NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(warning, LogLevel.Warn);
                    _log = LogManager.GetLogger("Portal");
                }

                return _log;
            }
        }

        /// <summary>
        /// Writes an Error to the log.
        /// </summary>
        /// <param name="ex"></param>
        public static void PublishException(Exception ex)
        {
            Log.Error(string.Format("\t{0}{1}{2}{3}{4}", GetCalleeString(), Environment.NewLine, ex.Message, Environment.NewLine, ex.StackTrace));
        }

        /// <summary>
        /// Writes an Error to the log.
        /// </summary>
        /// <param name="ex"></param>
        public static void LogMessage(string message)
        {
            Log.Error(string.Format(":\t{0}{1}\t{2}", GetCalleeString(), Environment.NewLine, message));
        }

        public static void LogMessageEvent(string message)
        {
            Log.Error(string.Format(":\t{0}{1}\t{2}", GetCalleeString(), Environment.NewLine, message));
        }

        /// <summary>
        /// Writes an Error to the log.
        /// </summary>
        /// <param name="ex"></param>
        public static void Warning(string message)
        {
            Log.Warn(string.Format(":\t{0}{1}\t{2}", GetCalleeString(), Environment.NewLine, message));
        }

        /// <summary>
        /// Writes an Debug to the log.
        /// </summary>
        /// <param name="ex"></param>
        public static void Debug(string message)
        {
            Log.Error(string.Format(":\t{0}{1}\t{2}", GetCalleeString(), Environment.NewLine, message));
        }

        public static string GetValueOfObject(object ob)
        {
            StringBuilder sb = new StringBuilder();
            try
            {
                foreach (System.Reflection.PropertyInfo piOrig in ob.GetType().GetProperties())
                {
                    object editedVal = ob.GetType().GetProperty(piOrig.Name).GetValue(ob, null);
                    sb.AppendFormat("{0}:{1}\t ", piOrig.Name, editedVal);
                }
            }
            catch
            {
            }
            return sb.ToString();
        }

        private static string GetCalleeString()
        {
            foreach (StackFrame sf in new StackTrace().GetFrames())
            {
                if (!string.IsNullOrEmpty(sf.GetMethod().ReflectedType.Namespace) && !typeof(NLogManager).FullName.StartsWith(sf.GetMethod().ReflectedType.Namespace))
                {
                    return string.Format("{0}.{1} ", sf.GetMethod().ReflectedType.Name, sf.GetMethod().Name);
                }
            }

            return string.Empty;
        }
    }
}